feat: wire regex support into CLI — UX messaging, --regex-hint, docs, homepage#114
feat: wire regex support into CLI — UX messaging, --regex-hint, docs, homepage#114
Conversation
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
🔦 Lighthouse Report
|
There was a problem hiding this comment.
Pull request overview
Adds first-class “regex query” support to github-code-search by translating /pattern/flags queries into a safe GitHub REST API query plus a local post-filter, and updates aggregation/highlighting so match segments align with actual regex matches.
Changes:
- Introduces
src/regex.tsto detect/pattern/flags, derive an API search term (incl. top-level alternation →OR), and compile a localRegExp. - Extends the CLI with
--regex-hintand wires regex parsing into the search flow; updates aggregation to recomputeTextMatchSegments from the regex matches. - Updates docs/README and UI docs components to document and showcase regex queries; adds tests for the new behavior.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/regex.ts | New regex-query parser: extracts regex token, derives API term, returns compiled RegExp for local filtering. |
| src/regex.test.ts | Unit tests for regex detection and API-term derivation behavior. |
| src/aggregate.ts | Adds optional regexFilter path to drop non-matching fragments and recompute match segments from regex results. |
| src/aggregate.test.ts | Tests repo/file filtering under regexFilter and validates recomputed segment indices/line/col. |
| github-code-search.ts | Adds --regex-hint and integrates regex mode into the CLI search pipeline. |
| README.md | Documents regex search as a new use case with an example invocation. |
| docs/usage/search-syntax.md | Adds a dedicated “Regex queries” section with examples, hints, and caveats. |
| docs/reference/cli-options.md | Adds --regex-hint to the CLI options reference. |
| docs/architecture/components.md | Updates the C4 component diagram to include the new regex parser component. |
| docs/.vitepress/theme/UseCaseTabs.vue | Adds a “Semver / version audit” use case tab using regex query syntax. |
| docs/.vitepress/theme/ComparisonTable.vue | Adds “Regex queries” as a comparison feature and links to docs. |
| AGENTS.md | Documents the new src/regex.ts module in the repository map. |
When a regex query is active, the GitHub API returns TextMatchSegments
pointing at the literal search term (e.g. 'axios'), not at the full
regex match ('axios": "1.12'). highlightFragment() was therefore
bold-yellowing only the literal fragment.
Fix: in aggregate(), when regexFilter is set, run the regex against each
fragment and replace API-provided segments with TextMatchSegments derived
from the actual regex match positions (correct 1-based line/col).
TextMatch entries where the regex finds no match are filtered out.
Add 3 new test cases: exact segment positions, multiline line/col, and
partial textMatches filtering.
Closes part of #112
- Parse /pattern/flags in query subcommand via isRegexQuery() / buildApiQuery() - Pass regexFilter to aggregate(); display UX warning when query is broadened - Add --regex-hint <term> escape hatch for edge cases - docs/usage/search-syntax.md: new Regex queries section with 4 examples - docs/reference/cli-options.md: document --regex-hint flag - docs/architecture/components.md: add src/regex.ts to C4 Level 3a diagram - docs/.vitepress/theme/ComparisonTable.vue: add Regex queries row (web UI only note) - docs/.vitepress/theme/UseCaseTabs.vue: add Semver / version audit use case - AGENTS.md: add src/regex.ts entry + symptom table row - README.md: add Regex search use case Closes #112
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
…docs code block lang
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
…ror, completions --regex-hint, fix comment
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
…ateElementStyle hex
|
Coverage after merging feat/regex-cli into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** Options that affect the generated replay command. */ | ||
| /** Wraps `s` in POSIX single quotes, escaping any embedded single quotes as '\''. | ||
| * Produces output that is safe to paste into bash / zsh regardless of the | ||
| * content (no `$()`, backtick, or glob expansion). */ |
| ): string { | ||
| const { format, outputType, includeArchived, groupByTeamPrefix } = options; | ||
| const parts: string[] = [ | ||
| `github-code-search ${JSON.stringify(query)} --org ${org} --no-interactive`, | ||
| ]; | ||
| const { format, outputType, includeArchived, groupByTeamPrefix, regexHint } = options; | ||
| const parts: string[] = [`github-code-search ${shellQuote(query)} --org ${org} --no-interactive`]; | ||
|
|
||
| const excludedReposList: string[] = [...excludedRepos].map((r) => shortRepo(r, org)); |
| /** 1-based absolute file line (computed by api.ts / recomputeSegments in aggregate.ts). | ||
| * Used for `#L{line}` GitHub anchors in output.ts. */ |
|
|
||
| ```mermaid | ||
| %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Poppins, Aestetico, Arial, sans-serif", "primaryColor": "#66CCFF", "primaryTextColor": "#000000", "lineColor": "#0000CC", "tertiaryColor": "#FFCC33"}, "themeCSS": ".label,.nodeLabel,.cluster-label > span{font-family:Poppins,Arial,sans-serif;letter-spacing:.2px} .cluster-label > span{font-weight:600;font-size:13px} .edgePath .path{stroke-width:2px}"}}%% | ||
| %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Poppins, Aestetico, Arial, sans-serif", "primaryColor": "#9933FF", "primaryTextColor": "#ffffff", "lineColor": "#0000CC", "tertiaryColor": "#FFCC33"}, "themeCSS": ".label,.nodeLabel,.cluster-label > span{font-family:Poppins,Arial,sans-serif;letter-spacing:.2px} .cluster-label > span{font-weight:600;font-size:13px} .edgePath .path{stroke-width:2px}"}}%% |
| ```mermaid | ||
| %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Poppins, Aestetico, Arial, sans-serif", "primaryColor": "#66CCFF", "primaryTextColor": "#000000", "lineColor": "#0000CC", "tertiaryColor": "#FFCC33"}, "themeCSS": ".label,.nodeLabel,.cluster-label > span{font-family:Poppins,Arial,sans-serif;letter-spacing:.2px} .cluster-label > span{font-weight:600;font-size:13px} .edgePath .path{stroke-width:2px}"}}%% | ||
| %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Poppins, Aestetico, Arial, sans-serif", "primaryColor": "#9933FF", "primaryTextColor": "#ffffff", "lineColor": "#0000CC", "tertiaryColor": "#FFCC33"}, "themeCSS": ".label,.nodeLabel,.cluster-label > span{font-family:Poppins,Arial,sans-serif;letter-spacing:.2px} .cluster-label > span{font-weight:600;font-size:13px} .edgePath .path{stroke-width:2px}"}}%% | ||
| C4Component |
Closes #112
Depends on #111 (already merged via
feat/regex-core)Root cause / context
The GitHub REST API does not support
/pattern/flagsregex syntax. Issue #111 added the coresrc/regex.tsmodule +aggregate()filter. This PR wires that into the CLI and documents it end-to-end.What changed
CLI (
github-code-search.ts)isRegexQuery()and derive the API query + client-side filter viabuildApiQuery()regexFilterdown toaggregate()/axios": "1\.12/→ API receivesaxios)--regex-hint <term>escape hatch to override the auto-derived literal seedHighlight fix (
src/aggregate.ts)regexFilteris active, replace API-providedTextMatchSegment[](pointing at the literal seed) with segments recomputed from actual regex match positions in each fragmentTextMatchentries where the regex finds no match are also filtered outDocs
docs/usage/search-syntax.md— new Regex queries section with 4 examples + tip/warning admonitionsdocs/reference/cli-options.md—--regex-hintflag documenteddocs/architecture/components.md—src/regex.tsadded to C4 Level 3a diagramAGENTS.md— module map entry + symptom table row forsrc/regex.tsREADME.md— Regex search use caseHomepage
ComparisonTable.vue— new row Regex queries (/pattern/flags): ✗gh search code(REST API), ✓github-code-search— note clarifies GitHub supports regex in the web UI onlyUseCaseTabs.vue— new tab Semver / version audit illustrating/\"axios\": \"1./for finding repos pinned to a vulnerable minor versionHow to test
Validation